import Flutter
import UIKit
import CoreBluetooth



@main
@objc class AppDelegate: FlutterAppDelegate, CBPeripheralManagerDelegate, CBCentralManagerDelegate, CBPeripheralDelegate {
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        
    }
    
    private let CHANNEL = "com.signage.signage/l2cap"
    private var methodChannel: FlutterMethodChannel?
    
    private var centralManager: CBCentralManager?
    private var connectedPeripherals: [String: CBPeripheral] = [:]
    private var l2capChannels: [String: CBL2CAPChannel] = [:]
    private var pendingResults: [String: FlutterResult] = [:]
    
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller = window?.rootViewController as! FlutterViewController
        
        // 确保在设置 channel 之前完成基础初始化
        GeneratedPluginRegistrant.register(with: self)
        
        methodChannel = FlutterMethodChannel(
            name: CHANNEL,
            binaryMessenger: controller.binaryMessenger)
        
        methodChannel?.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) in
            switch call.method {
            case "createL2capChannel":
                self?.createL2capChannel(call, result: result)
            case "sendL2capData":
                self?.sendL2capData(call, result: result)
            case "closeL2capChannel":
                self?.closeL2capChannel(call, result: result)
            case "getL2capMtu":
                self?.getL2capMtu(call, result: result)
            default:
                result(FlutterMethodNotImplemented)
            }
        }
        
        centralManager = CBCentralManager(delegate: self, queue: nil)
        
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
    
    private func createL2capChannel(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any],
              let deviceId = args["deviceId"] as? String,
              let psm = args["psm"] as? Int else {
            result(FlutterError(code: "INVALID_ARGUMENT", message: "Invalid arguments", details: nil))
            return
        }
        
        // Close existing channel if any
        if let existingChannel = l2capChannels[deviceId] {
            l2capChannels.removeValue(forKey: deviceId)
        }
        
        guard let peripheral = connectedPeripherals[deviceId] else {
            // If peripheral not connected, connect first
            guard let uuid = UUID(uuidString: deviceId) else {
                result(FlutterError(code: "INVALID_DEVICE_ID", message: "Invalid device ID format", details: nil))
                return
            }
            
            pendingResults[deviceId] = result
            // 修复：先检索外设，然后再连接
            let peripherals = centralManager?.retrievePeripherals(withIdentifiers: [uuid])
            if let peripheral = peripherals?.first {
                connectedPeripherals[deviceId] = peripheral
                centralManager?.connect(peripheral, options: nil)
            } else {
                result(FlutterError(code: "DEVICE_NOT_FOUND", message: "Device not found", details: nil))
            }
            return
        }
        
        // Open L2CAP channel
        peripheral.openL2CAPChannel(UInt16(psm))
    }
    
    private func sendL2capData(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any],
              let deviceId = args["deviceId"] as? String,
              let data = args["data"] as? FlutterStandardTypedData else {
            result(FlutterError(code: "INVALID_ARGUMENT", message: "Invalid arguments", details: nil))
            return
        }
        
        guard let channel = l2capChannels[deviceId] else {
            result(FlutterError(code: "NOT_CONNECTED", message: "L2CAP channel not connected", details: nil))
            return
        }
        
        // Send data in chunks
        let chunkSize = 1024 // Adjust based on your needs
        let rawData = data.data
        var offset = 0
        
        while offset < rawData.count {
            let remainingBytes = rawData.count - offset
            let length = min(chunkSize, remainingBytes)
            let chunk = rawData.subdata(in: offset..<(offset + length))
            
            channel.outputStream.write((chunk as NSData).bytes.assumingMemoryBound(to: UInt8.self), maxLength: length)
            offset += length
        }
        
        result(nil)
    }
    
    private func closeL2capChannel(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any],
              let deviceId = args["deviceId"] as? String else {
            result(FlutterError(code: "INVALID_ARGUMENT", message: "Device ID is required", details: nil))
            return
        }
        
        if let channel = l2capChannels[deviceId] {
//            channel.cancel()
            l2capChannels.removeValue(forKey: deviceId)
        }
        
        result(nil)
    }
    
    private func getL2capMtu(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        guard let args = call.arguments as? [String: Any],
              let deviceId = args["deviceId"] as? String,
              let channel = l2capChannels[deviceId] else {
            result(FlutterError(code: "NOT_CONNECTED", message: "L2CAP channel not connected", details: nil))
            return
        }
        
        let params: [String: Any] = [
            "deviceId": deviceId,
            "sendMtu": channel.outputStream.streamStatus == .open ? 1024 : 0, // Example value
            "receiveMtu": channel.inputStream.streamStatus == .open ? 1024 : 0, // Example value
            "isConnected": channel.outputStream.streamStatus == .open
        ]
        
        result(params)
    }
    
    // MARK: - CBCentralManagerDelegate
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        print("Central manager state updated: \(central.state)")
    }
    
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        peripheral.delegate = self
        connectedPeripherals[peripheral.identifier.uuidString] = peripheral
        
        if let result = pendingResults[peripheral.identifier.uuidString] {
            result(nil)
            pendingResults.removeValue(forKey: peripheral.identifier.uuidString)
        }
    }
    
    // MARK: - CBPeripheralDelegate
    
    func peripheral(_ peripheral: CBPeripheral, didOpen channel: CBL2CAPChannel?, error: Error?) {
        let deviceId = peripheral.identifier.uuidString
        
        if let error = error {
            if let result = pendingResults[deviceId] {
                result(FlutterError(code: "L2CAP_ERROR", message: error.localizedDescription, details: nil))
                pendingResults.removeValue(forKey: deviceId)
            }
            return
        }
        
        if let channel = channel {
            l2capChannels[deviceId] = channel
            
            if let result = pendingResults[deviceId] {
                result(nil)
                pendingResults.removeValue(forKey: deviceId)
            }
        }
    }
}
